﻿
using System;
using System.Diagnostics;

namespace UnsafeAndFixed
{
    class Program
    {
        static void SafeOperation(int[,] matrix)
        {
            int n = matrix.GetLength(0);
            int m = matrix.GetLength(1);

            for (int i = 0; i < n; ++i)
            {
                for (int j = 0; j < m; ++j)
                {
                    matrix[i, j] *= matrix[i, j];
                }                
            }
        }

        unsafe static void UnSafeOperation(int[,] matrix)
        {
            int len = matrix.Length;

            fixed (int* first = matrix)
            {
                int* p = first;

                for (int i = 0; i < len; ++i, ++p)
                {
                    *p *= *p;
                }
            }
        }

        static void Initialize(int[,] matrix)
        {
            int n = matrix.GetLength(0);
            int m = matrix.GetLength(1);

            for (int i = 0; i < n; ++i)
            {
                for (int j = 0; j < m; ++j)
                {
                    matrix[i, j] = (i + 1) * (j + 1);
                }
            }
        }

        static void Print(int[,] matrix)
        {
            int n = matrix.GetLength(0);
            int m = matrix.GetLength(1);

            for (int i = 0; i < n; ++i)
            {
                for (int j = 0; j < m; ++j)
                {
                    Console.Write(matrix[i, j] + "\t");
                }

                Console.WriteLine();
            }
            Console.WriteLine();
            Console.WriteLine();
        }

        static void Main()
        {
            const int n = 10000;
            const int m = 10000;

            var matrix = new int[n, m];

            Initialize(matrix);

            var timer = new Stopwatch();

            timer.Start();
            SafeOperation(matrix);
            timer.Stop();

            double safeTime = timer.Elapsed.TotalSeconds;
            Console.WriteLine("Safe time: {0}", safeTime);

            Initialize(matrix);

            timer.Reset();
            timer.Start();
            UnSafeOperation(matrix);
            timer.Stop();

            double unsafeTime = timer.Elapsed.TotalSeconds;
            Console.WriteLine("Unsafe time: {0}", unsafeTime);

            Console.WriteLine("Unsafe is {0} times faster", safeTime / unsafeTime);
        }
    }
}
